构建之法 邹欣 Notes

构建之法(第二版) 邹欣

第一版前言

2016-02-17

20世纪末,有人问软件工程专家戴维·帕纳斯(David Parnas):将来会有什么令人兴奋的软件工程技术出现?他回答:

最有用的技术不在将来,而是已经出现好些年了,只不过我们没好好用。

2016-02-17

这是我和本书的出版人、来自独立出版团队JUSTPUB的周筠老师合作的第三本书,她是我唯一的出版人,同时也是最好的一个。

2016-02-17

最后,要感谢我的家人,他们容忍我一个人在厨房里对着电脑长时间发呆,有时还给我煮绿豆汤喝!

1.1 软件 = 程序 + 软件工程

2016-02-17

程序=数据结构+算法”

2016-02-17

我上班后,发现以前同事写的程序真是垃圾,根本看不懂,无法维护。我要推翻重写!后来一个老员工笑嘻嘻地告诉我,我们现在看到的程序,就是去年的新员工愤怒地推翻重写之后的结果,大家反映还没有以前的版本好用呢。

2016-02-17

程序,在这里指的是源程序,就是一行行的代码。它们是建立在数据结构上的一些算法。程序还要对数据进行操作,这些数据有些是静态的(例如软件的图标、提示信息),有些是动态的(例如程序生成的随机数字、程序通过网络下载的数据、用户的文字或语音输入等)。但是光有代码和静态数据还是不行,工程师要把它们构建为机器能懂的可执行代码。构建不仅仅是cc和link命令,一个复杂的软件不但要有合理的软件架构(Software Architecture)、软件设计与实现(Software Design, Implementation and Debug),还要有各种文件和数据来描述各个程序文件之间的依赖关系、编译参数、链接参数,等等。这些都是软件构建的过程。

2016-02-17

软件团队的成员每天都在修改各种源代码,怎么保证软件在修改过程中能不断提高质量,至少要维持以前的质量?有些时候,我们要为某个需求写一些特殊功能,不久后又要把这些功能再合并回主要版本。有些程序要配置不同的界面,运行在中文、英文或其他语言的操作系统上;有些程序还有32位版本、64位版本等。这是源代码管理(Source Code Control)的问题—有时候也叫配置管理(Software Configuration Management)。我们还有一系列的工具、流程和文档来保证程序的正确性,这些工具(也是软件)、流程应该达到很高的质量,才能保证开发出来的软件的质量。这就是质量保障(Quality Assurance),具体的验证过程叫做软件测试(Testing)。

一个软件或者服务要有人买,就得找到顾客,顾客有各种需求,有些靠谱,有些不靠谱;有些容易做到,有些难以做到。软件团队要从需求分析(Requirement Analysis)开始,把合适的需求梳理出来,然后逐步展开后续工作,如设计(软件架构)、实现(写数据结构和算法)、测试,到最后发布软件。

软件团队的人员也会流动,新的成员要尽快读懂已有的程序,了解程序的设计,这叫程序理解(Program Comprehension)。软件在运行过程中还会出这样那样的问题,也许我们要时不时给软件打一个补丁,或者维护众多的服务,团队的新老成员要一起修复各种各样的问题,这叫软件维护(Software Maintenance),或者服务运营(Service Operation)。这一系列过程就是软件的生命周期(Software Life Cycle,SLC),有人得负责软件项目的管理(Project Management)。

一个好的软件,即使功能和同类软件区别不大,但却会让人感觉到非常好用。这就是软件的用户体验(User Experience)。用户体验和数据结构、算法没有直接的关系,但是很多非常成功的软件就赢在这个方面。

2016-02-17

当然还有在用户不知道的情况下就安装了软件,然后用户怎么也摆脱不掉。2010年,中国还出了一桩怪事:A公司要挟用户必须卸载B公司的软件,然后A公司的软件才能运行……这些软件企业的商业模式有些是合情合理也合法;有些看似合情合理,但是不怎么合法;有些做法不合理,但是还没有出台相关法律。在相关法律完善之前,软件行业还有一个行规,即应该有职业道德规范来约束IT人的行为。

2016-02-17

软件企业 = 软件 + 商业模式

2016-02-17

程序(算法、数据结构)是基本功,但是在算法和数据结构之上,软件工程决定了软件的质量;商业模式决定了一个软件企业的成败。软件从业人员和软件企业的道德操守会极大地影响软件用户的利益。

2016-02-17

“设计/制造纸飞机”的过程,看起来技术含量不高,但是也有很多窍门。有些小孩在放飞前,会用嘴对着纸飞机哈一口气,这里面也许有深奥的道理,也许只是迷信。在跟着这些飞机奔跑、欢呼的时候,这些小孩心里一定有“我长大了,要开飞机在天上飞”的想法。纸飞机、航模飞机和真飞机一样,都体现了某些基本的理论。图1-1 纸飞机——玩具阶段

\2. 业余爱好阶段

多年以后,很多人还有“在天上飞”的想法。有人居然就实现了注释2:

2016-02-17

肯特·柯西(Kent Couch),一位美国俄勒冈州的居民,在2007年用一百多个氦气球和一把椅子飞上了天。他说,“当你夏天躺在草地上的时候,看到白云飘过,你有没有幻想能跳到云朵上面?”所以他有一天忍不住就要实现他的梦想注释3。

2016-02-17

在成熟的航空工业中,一个飞机发动机从构思到最后运行,不知道要经历过多少人、多少工序、多少流程、多少相关知识的验证。我们无法想象,某个商用型号的发动机在飞行时发现问题,最初的设计师会自己爬到引擎中敲敲打打,然后钻出来说:“继续飞吧,我搞定了。”然而,在软件行业中,很多软件工程师往往以做这样的事而自豪。

2016-02-17

试想这样的事发生在我们的程序中,程序正在高速运行,突然发生了一个异常,我们的程序能否正常工作,安然退出,并保证用户的数据不被破坏

1.2 软件工程是什么

2016-02-17

软件工程是把系统的、有序的、可量化的方法应用到软件的开发、运营和维护上的过程。

软件工程包括下列领域:软件需求分析、软件设计、软件构建、软件测试和软件维护。

软件工程和下列的学科相关:计算机科学、计算机工程、管理学、数学、项目管理学、质量管理、软件人体工学、系统工程、工业设计和用户界面设计。

2016-02-17

随着人类社会的发展,技术的进步,一些事情总是变得越来越容易,例如旅行,现在人们旅行的方便程度和速度是几百年前所不可想象的。另一些事情,像怀孕生小孩,几千年来的确变得比较容易了,但还是需要大约九个月的时间,生小孩的“成本”也许更大了

2016-02-17

. 复杂性(Complexity)

软件可以说是人类创造的最复杂的系统类型。大型软件(操作系统、办公软件、搜索引擎)有超过百万行的源代码,上万个不同的文件。而软件工程师的肉眼通常一次只能看到30—80行源代码(相当于显示器的一屏),他们的智力、记忆力和常人差不多,在过去的几十年中并没有大的提高。软件的各个模块之间有各种显性或隐性的依赖关系,随着系统的成长和模块的增多,这些关系的数量往往以几何级数的速度增长。而理解运用这些复杂性的人并没有太大的变化。

\2. 不可见性(Invisibility)

软件工程师能直接看见源代码,但是源代码不是软件本身。软件以机器码的形式高速运行,还可能在几个CPU核上同时运行,工程师是“看”不到自己的源代码如何具体地在用户的机器上被执行的。商用软件出现了错误,工程师可以看到程序在出错的一瞬间留下的一些痕迹(错误代号、大致的目标代码位置、错误信息),但是几乎无法完整重现到底程序出现了什么问题。

\3. 易变性(Changeability)

软件看上去很容易修改,修改软件比修改硬件容易多了。人们自然地期待软件能在下面两种情况下“改变”:a)让软件做新的事情;b)让软件适应新的硬件。但是与此同时,正确地修改软件是一件很困难的事情。

\4. 服从性(Conformity)

软件不能独立存在,它总是要运行在硬件上面,它要服从系统中其他组成部分的要求,它还要服从用户的要求、行业系统的要求(例如银行利率的变化)。

\5. 非连续性(Discontinuity)人们比较容易理解连续的系统:增加输入,就能看到相应输出的增加。但是许多软件系统却没有这样的特性,有时输入上很小的变化,会引起输出上极大的变化。

这些特性的前四个是佛瑞德·布鲁克斯(Fred Brooks Jr.)在No Silver Bullet一文中提到的,第五个特性是瓦茨拉夫·拉里奇(Vaclav Rajlich)提到的。

这些特性是由软件的本质所决定的,软件还有其他特性:

有许多不同的程序设计语言、软件工具和软件开发平台

存在许多不同的软件开发流程

软件团队中存在许多不同的角色

软件既可以存储在磁带上,也可以存储在CD/DVD上

2016-02-17

这些事并不能改变软件工程的根本难度,这也是著名的“没有银弹(No Silver Bullet)”论断所阐述的道理

2016-02-17

创造性地运用科学原理,设计和实现建筑、机器、装置或生产过程;或者是在实践中使用一个或多个上述实体;或者是实现这些实体的过程

2016-02-17

和数理化相比,计算机科学是一门相当年轻的学科,虽然我们可以追溯到巴贝奇(Charles Babbage,1791—1871)、埃达(Ada Lovelace,1815—1852)、图灵(Alan Turing,1912—1954)等计算机科学的先驱,但是“Computer Science”这个学科的名字是1959年才正式提出,综合维基百科中“计算机科学”的词条和微软学术搜索(Microsoft Academic Search)注释9对于计算机科学子领域的划分,计算机科学(Computer Science)这一学术领域可以分为下面这些偏理论的领域:计算理论(Theoretical Computing)

信息和编码理论(Information and Coding Theory)

算法和数据结构(Algorithm and Data Structure)

形式化方法(Formal Methods)

程序设计语言(Programming Language)

以及下面这些偏实践的领域:

计算机体系结构(Computer Architecture)

并行计算和分布式系统(Concurrent, Parallel and Distributed System)

实时系统和嵌入式系统(Real Time and Embedded System)

操作系统(Operating System)

计算机网络(Networking)

科学计算(Scientific Computing)

安全和密码学(Security and Cryptography)

人工智能(Artificial Intelligence)

这个领域涵盖了许多相关的领域,如模式识别(Pattern Recognition)、机器学习(Machine Learning)、数据挖掘(Data Mining)、信息提取(Information Retrieval)等。

计算机图形学(Computer Graphics)、计算机视觉(Computer Vision)、多媒体(Multimedia)

数据库和大规模数据处理(Database and Large Scale Data Processing)

万维网(World Wide Web)

自然语言处理和语音(Natural Language Processing and Speech)

人机交互(Human Computer Interaction)

软件工程(Software Engineering)

2016-02-17

可以看到,计算机科学中的理论研究部分,大多可以从形式上证明,与数学、离散数学、数理逻辑密切相关;计算机科学中与实践相关的部分,都和数据以及其他学科发生关系;软件工程则和人的行为、现实社会的需求息息相关。软件工程的研究目标(软件的开发、运营和维护)中都有“人”出现,这些“人”可以是项目需求的提供者,可以是软件的开发人员,还可以是软件的用户。